package com.dingreading.cloud.ssxcx.util;

import com.dingreading.cloud.ssxcx.dto.SubjectTreeDto;
import com.dingreading.cloud.ssxcx.dto.SubjectsDto;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;

import java.util.*;

public class XcxAttendClassUtils {
    /**
     * 使用Map将扁平列表高效地构建成树形结构。
     * 此版本使用唯一的 ID 作为 Map 的键，是构建树的标准且最高效的方法。
     *
     * @param subjectsDtoList 扁平的科目列表
     * @return 树形结构的科目列表 (只包含根节点)
     */
    public static List<SubjectTreeDto> buildTree(List<SubjectsDto> subjectsDtoList) {
        if (CollectionUtils.isEmpty(subjectsDtoList)) {
            return new ArrayList<>();
        }

        List<SubjectTreeDto> tree = new ArrayList<>();
        // 关键改动：使用唯一的 ID 作为 Map 的 key，用于快速查找任何节点
        Map<Long, SubjectTreeDto> map = new HashMap<>(subjectsDtoList.size());

        // 1. 转换 DTO 并用其唯一 ID 填充 Map
        for (SubjectsDto dto : subjectsDtoList) {
            SubjectTreeDto node = new SubjectTreeDto();
            BeanUtils.copyProperties(dto, node);
            // 使用 node.getId() 作为唯一的 key
            map.put(node.getId(), node);
        }

        // 2. 遍历 Map，组装父子关系
        for (SubjectTreeDto node : map.values()) {
            Long parentId = node.getParentId();

            // 判断是否为根节点 (parentId 为 null 或 0)
            if (parentId == null || parentId == 0L) {
                tree.add(node);
            } else {
                // 如果是子节点，从 map 中根据 parentId 找到它的父节点
                SubjectTreeDto parentNode = map.get(parentId);
                if (parentNode != null) {
                    // 将当前节点加入父节点的 children 列表中
                    parentNode.getChildren().add(node);
                } else {
                    // 如果找不到父节点 (数据不一致或父节点不在本次查询结果中)，也将其视为根节点
                    tree.add(node);
                }
            }
        }

        // 3. 对树的每一层级进行排序
        sortTreeNodes(tree);

        return tree;
    }

    /**
     * 递归地对树的每个层级的子节点进行排序
     * @param nodes 要排序的节点列表
     */
    private static void sortTreeNodes(List<SubjectTreeDto> nodes) {
        if (CollectionUtils.isEmpty(nodes)) {
            return;
        }

        Comparator<SubjectTreeDto> comparator = Comparator.comparing(
                node -> node.getSubjectOrder() != null ? node.getSubjectOrder() : Integer.MAX_VALUE
        );

        nodes.sort(comparator);

        for (SubjectTreeDto node : nodes) {
            sortTreeNodes(node.getChildren());
        }
    }
}
